package com.globallogic.token;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import com.globallogic.inout.Out;

public class TokenProcessor implements Iterable<TokenProcessor>{
	
	public int getChildCount() {
		
		return tokenProcessorList.size();
		
	}
	
	public String getHelpString(){
		
		return this.getToken() + this.getDescription();
		
	} 
	
	public void handle (List<String> params) {
		
		TokenProcessor tokenProcessor = null;

		if (null != tokenHandler) {
            
			tokenHandler.execute(this, params);
			
			return;
			
		}
		
		tokenProcessor = tokenProcessorList.get(params.get(0).toLowerCase());
		
		if (null != tokenProcessor) {
			
			params.remove(0);
			tokenProcessor.handle(params);
			
		} else {
			
			noSuchToken(params.get(0));
			
		}
		
	}
	
	public TokenProcessor(String token, TokenType tokenType,
						  TokenHandler tokenHandler, TokenProcessor parentTokenProcessor) {

		this.token = token;
		this.tokenType = tokenType; 
		this.tokenHandler = tokenHandler;
		this.parentTokenProcessor = parentTokenProcessor;
		
		tokenProcessorList = new HashMap<String, TokenProcessor>(); 
	}

	public void addChildTokenProcessor(TokenProcessor tokenProcessor) {
		
		tokenProcessorList.put(tokenProcessor.getToken(), tokenProcessor);
		
	}

	public String getToken() { return this.token; }

	private void noSuchToken(String token) {

		Out.printLn("No such " + tokenType + ": " + token.toLowerCase());
		Out.printLn("Available " + tokenType +"s are: ");
		
		for (TokenProcessor tokenProcessor : tokenProcessorList.values()) {

			Out.printLn(tokenProcessor.getToken());
		
		}
		
	}
	
	public TokenProcessor getParentTokenProcessor() {
		return parentTokenProcessor;
	}

    
	@Override
	public Iterator<TokenProcessor> iterator() {

		return new TokenProcessorIterator();
	
	}
	
	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		
		this.description = description;
		
	}

	class TokenProcessorIterator implements Iterator<TokenProcessor> {

		public TokenProcessorIterator(){
			
			tokenProcessorIterator = TokenProcessor.this.tokenProcessorList.values().iterator();			
			
		}
		
		@Override
		public boolean hasNext() {

			return tokenProcessorIterator.hasNext();
		}
		
		@Override
		public TokenProcessor next() {

			return tokenProcessorIterator.next();
			
		}

		@Override
		public void remove() {

			throw new UnsupportedOperationException();
			
		}
        
		private Iterator<TokenProcessor> tokenProcessorIterator;

	} 

	private String token;
    private TokenHandler tokenHandler;
    private HashMap<String, TokenProcessor> tokenProcessorList; 

	private TokenType tokenType;
    private TokenProcessor parentTokenProcessor;
	private String description;
}
